#include "ConfigManager.hpp"
#include <QtCore/QFile>
#include <QtXml/QDomAttr>
#include <QtXml/QDomNode>
#include <QtXml/QDomElement>
#include <QtXml/QDomDocument>

ConfigManager::ConfigManager() {
    collection=QVector<QString>();
    shortcuts=QVector<Shortcut*>();
    cfgFile.setFileName(CONFIG_FILE);
    out.setDevice(&cfgFile);
    cfgFile.open(QIODevice::ReadWrite);
    if(!load()) {
        setDefaultConfiguration();
        save();
    }
}
ConfigManager::~ConfigManager() {
    save();
    cfgFile.close();
}

bool ConfigManager::load() {
    if(!cfgFile.exists()) return false;
    QXmlInputSource inputSource(&cfgFile);
    QXmlSimpleReader reader;
    reader.setContentHandler(this);
    if(!reader.parse(&inputSource)) return false;
    return true;
}
void ConfigManager::save() {
    QString value;
    QDomDocument doc;
    QDomElement configItem=doc.createElement("configuration");
    doc.appendChild(configItem);
    QDomElement e;
    e=doc.createElement("parameter"); e.setAttribute("name","fadeInTime"); e.setAttribute("value",value.setNum(fadeInTime)); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","fadeOutTime"); e.setAttribute("value",value.setNum(fadeOutTime)); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","replayGainPreAmp"); e.setAttribute("value",value.setNum(replayGainPreAmp)); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","bufferTime"); e.setAttribute("value",value.setNum(bufferTime)); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","songInfoFontSize"); e.setAttribute("value",value.setNum(songInfoFontSize)); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","preferredCover"); e.setAttribute("value",preferredCover); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","proxy"); e.setAttribute("value",proxy); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","notificationCustomBrief"); e.setAttribute("value",notificationCustomBrief); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","notificationCustomBody"); e.setAttribute("notificationCustomBody",proxy); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","fadeOnStop"); e.setAttribute("value",fadeOnStop?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","fadeOnSkip"); e.setAttribute("value",fadeOnSkip?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","fadeOnNext"); e.setAttribute("value",fadeOnNext?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","fadeForAlbum"); e.setAttribute("value",fadeForAlbum?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","useReplayGainIfAvailable"); e.setAttribute("value",useReplayGainIfAvailable?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","replayGainApplyCompression"); e.setAttribute("value",replayGainApplyCompression?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","monoPlayback"); e.setAttribute("value",monoPlayback?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","updateCollectionAtStartup"); e.setAttribute("value",updateCollectionAtStartup?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","monitorOnChangeOnCollection"); e.setAttribute("value",monitorOnChangeOnCollection?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","displayMissing"); e.setAttribute("value",displayMissing?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","notificationOnVolumeChange"); e.setAttribute("value",notificationOnVolumeChange?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","notificationOnRepeatChange"); e.setAttribute("value",notificationOnRepeatChange?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","notificationHasAlbumCover"); e.setAttribute("value",notificationHasAlbumCover?"true":false); configItem.appendChild(e);
    e=doc.createElement("parameter"); e.setAttribute("name","notificationHasCustomText"); e.setAttribute("value",notificationHasCustomText?"true":false); configItem.appendChild(e);
    /// @todo add folders & shortcut
    QDomNode tmp=doc.createProcessingInstruction("xml","version=\"1.0\"");
    doc.insertBefore(tmp,doc.firstChild());
    cfgFile.resize(0);
    doc.save(out,2);
}

void ConfigManager::addFolder(QString f) {
    for(int i=0; i<collection.size(); i++)
        if(collection[i].compare(f)) return;
    collection.push_back(f);
}
void ConfigManager::setDefaultConfiguration() {
    setBufferTime();
    setDisplayMissing();
    setFadeForAlbum();
    setFadeInTime();
    setFadeOnNext();
    setFadeOnSkip();
    setFadeOnStop();
    setFadeOutTime();
    setMonitorOnChangeOnCollection();
    setMonoPlayback();
    setNotificationDuration();
    setNotificationHasAlbumCover();
    setNotificationHasCustomBody();
    setNotificationHasCustomBrief();
    setNotificationHasCustomText();
    setNotificationOnVolumeChange();
    setNotificationRepeatChange();
    setPrefferedCover();
    setProxySettings();
    setRemoveMissing();
    setReplayGainCompression();
    setReplayGainIfAvailable();
    setReplayGainPreAmp();
    setSongInfoFontSize();
    setSongInfoNetworkTimeout();
    setUpdateCollectionAtStartup();
}
//getters
bool ConfigManager::hasFadeOnStop() {return fadeOnStop;}
bool ConfigManager::hasFadeOnSkip() {return fadeOnSkip;}
bool ConfigManager::hasFadeOnNext() {return fadeOnNext;}
bool ConfigManager::hasFadeForAlbum() {return fadeForAlbum;}
unsigned int ConfigManager::getFadeInTime() {return fadeInTime;}
unsigned int ConfigManager::getFadeOutTime() {return fadeOutTime;}
bool ConfigManager::hasReplayGainEnabled() {return useReplayGainIfAvailable;}
bool ConfigManager::hasReplayGainCompression() {return replayGainApplyCompression;}
float ConfigManager::getReplayGainPreAmp() {return replayGainPreAmp;}
unsigned int ConfigManager::getBufferTime() {return bufferTime;}
bool ConfigManager::isMonoPlayback() {return monoPlayback;}
bool ConfigManager::hasUpdateOnCollectionAtStartup() {return updateCollectionAtStartup;}
bool ConfigManager::hasMonitorOnChangeCollection() {return monitorOnChangeOnCollection;}
bool ConfigManager::hasMissingDisplayed() {return displayMissing;}
QString ConfigManager::getPrefferedCovers() {return preferredCover;}
QVector<QString>* ConfigManager::getCollection() {return &collection;}
QString ConfigManager::getProxySettings() {return proxy;}
QVector<Shortcut*>* ConfigManager::getShortcuts() {return &shortcuts;}
float ConfigManager::getSongInfoFontSize() {return songInfoFontSize;}
unsigned int ConfigManager::getSongInfoNetworkTimeout() {return songInfoNetworkTimeout;}
unsigned int ConfigManager::getNotifyDuration() {return notificationDuration;}
bool ConfigManager::hasNotificationOnVolumeChange() {return notificationOnVolumeChange;}
bool ConfigManager::hasNotificationOnRepeatChange() {return notificationOnRepeatChange;}
bool ConfigManager::hasNotificationHasAlbumCover() {return notificationHasAlbumCover;}
bool ConfigManager::hasNotificationHasCustomText() {return notificationHasCustomText;}
QString ConfigManager::getNotificationCustomBrief() {return notificationCustomBrief;}
QString ConfigManager::getNotificationCustomBody() {return notificationCustomBody;}
/*QString ConfigManager::getTrackRenameMask() {return "";}
QString ConfigManager::getCompilationTrackRenameMask() {return "";}
QString ConfigManager::getAlbumRenameMask() {return "";}
QString ConfigManager::getCompilationRenameMask() {return "";}*/
//setters
void ConfigManager::setFadeOnStop(bool v) {fadeOnStop=v;}
void ConfigManager::setFadeOnSkip(bool v) {fadeOnSkip=v;}
void ConfigManager::setFadeOnNext(bool v) {fadeOnNext=v;}
void ConfigManager::setFadeForAlbum(bool v) {fadeForAlbum=v;}
void ConfigManager::setFadeInTime(unsigned int v) {fadeInTime=v;}
void ConfigManager::setFadeOutTime(unsigned int v) {fadeOutTime=v;}
void ConfigManager::setReplayGainIfAvailable(bool v) {useReplayGainIfAvailable=v;}
void ConfigManager::setReplayGainCompression(bool v) {replayGainApplyCompression=v;}
void ConfigManager::setReplayGainPreAmp(float v) {replayGainPreAmp=v;}
void ConfigManager::setBufferTime(unsigned int v) {bufferTime=v;}
void ConfigManager::setMonoPlayback(bool v) {monoPlayback=v;}
void ConfigManager::setDisplayMissing(bool v) {displayMissing=v;}
void ConfigManager::setRemoveMissing(bool v) {removeMissing=v;}
void ConfigManager::setUpdateCollectionAtStartup(bool v) {updateCollectionAtStartup=v;}
void ConfigManager::setMonitorOnChangeOnCollection(bool v) {monitorOnChangeOnCollection=v;}
void ConfigManager::setPrefferedCover(QString v) {preferredCover=v;}
void ConfigManager::setProxySettings(QString v) {proxy=v;}
void ConfigManager::setSongInfoFontSize(float v) {songInfoFontSize=v;}
void ConfigManager::setSongInfoNetworkTimeout(unsigned int v) {songInfoNetworkTimeout=v;}
void ConfigManager::setNotificationDuration(unsigned int v) {notificationDuration=v;}
void ConfigManager::setNotificationOnVolumeChange(bool v) {notificationOnVolumeChange=v;}
void ConfigManager::setNotificationRepeatChange(bool v) {notificationOnRepeatChange=v;}
void ConfigManager::setNotificationHasAlbumCover(bool v) {notificationHasAlbumCover=v;}
void ConfigManager::setNotificationHasCustomText(bool v) {notificationHasCustomText=v;}
void ConfigManager::setNotificationHasCustomBrief(QString v) {notificationCustomBrief=v;}
void ConfigManager::setNotificationHasCustomBody(QString v) {notificationCustomBody=v;}

//xml
bool ConfigManager::startElement ( const QString &, const QString &, const QString & qName, const QXmlAttributes & atts ) {
    if(qName=="parameter") {
        QString value=atts.value("value");
        if(atts.value("name")=="notificationCustomBody") notificationCustomBody=value;
        else if(atts.value("name")=="notificationCustomBrief") notificationCustomBrief=value;
        else if(atts.value("name")=="notificationHasAlbumCover") notificationHasAlbumCover=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="notificationOnRepeatChange") notificationOnRepeatChange=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="notificationOnVolumeChange") notificationOnVolumeChange=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="notificationDuration") notificationDuration=value.toUInt();
        else if(atts.value("name")=="songInfoNetworkTimeout") songInfoNetworkTimeout=value.toUInt();
        else if(atts.value("name")=="songInfoFontSize") songInfoFontSize=value.toFloat();
        else if(atts.value("name")=="proxy") proxy=value;
        else if(atts.value("name")=="preferredCover") preferredCover=value;
        else if(atts.value("name")=="monitorOnChangeOnCollection") monitorOnChangeOnCollection=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="updateCollectionAtStartup") updateCollectionAtStartup=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="removeMissing") removeMissing=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="displayMissing") displayMissing=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="monoPlayback") monoPlayback=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="bufferTime") bufferTime=value.toUInt();
        else if(atts.value("name")=="replayGainPreAmp") replayGainPreAmp=value.toFloat();
        else if(atts.value("name")=="replayGainApplyCompression") replayGainApplyCompression=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="useReplayGainIfAvailable") useReplayGainIfAvailable=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="fadeOutTime") fadeOutTime=value.toUInt();
        else if(atts.value("name")=="fadeInTime") fadeInTime=value.toUInt();
        else if(atts.value("name")=="fadeForAlbum") fadeForAlbum=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="fadeOnNext") fadeOnNext=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="fadeOnSkip") fadeOnSkip=value.compare("True", Qt::CaseInsensitive)?true:false;
        else if(atts.value("name")=="fadeOnStop") fadeOnStop=value.compare("True", Qt::CaseInsensitive)?true:false;
    } else if(qName=="list") {
        currentName=atts.value("name");
    } else if(qName=="item") {
        if(currentName=="collection") collection.push_back(atts.value("value"));
        else if(currentName=="shortcut") { //format: "global:stop:Ctrl+F11"
            int type=atts.value("value").indexOf(":"),name,shortcut;
            name=atts.value("value").indexOf(":",type);
            shortcut=atts.value("value").indexOf(":",name);
            Shortcut *s=new Shortcut(atts.value("value"), atts.value("value").left(type-1)=="global"?true:false);
            s->set(QKeySequence::fromString(atts.value("value").right(shortcut+1)));
        }
    } //else(qName=="configuration"); //we don't process the empty root element nor section for its name
    return true;
}

bool ConfigManager::fatalError (const QXmlParseException & exception) {
    return false; //pas traité ici
}
bool ConfigManager::characters ( const QString & ch) {return true;}
bool ConfigManager::endElement ( const QString &, const QString &, const QString & qName ) {
    currentName="";
    return true;
}

QString ConfigManager::getAuthorizedFormats(){return formats;}

bool ConfigManager::hasTags() {return onlyWithTags;}
unsigned int ConfigManager::getCountAfterTime() {return countAfterTime;}
void ConfigManager::setCountAfterTime(unsigned int t) {countAfterTime=t;}
bool ConfigManager::isVolumeReducedIsteadOfMuting() {return reduceVolumeInsteadOfMuting;}
bool ConfigManager::isResumingAtStartup() {return resumeAtStartup;}
unsigned int ConfigManager::getLastPositionPlayed() {return lastPositionPlayed;}
unsigned int ConfigManager::getVolume() {return volume;}
unsigned int ConfigManager::getRepeatMode() {return repeatMode;}
unsigned int ConfigManager::getShuffleMode() {return shuffleMode;}
unsigned int ConfigManager::getMinTime() {return minTime;}
unsigned int ConfigManager::getMaxTime() {return maxTime;}
unsigned short ConfigManager::getMinBitrate() {return minBitrate;}
unsigned short ConfigManager::getMaxBitrate() {return maxBitrate;}
unsigned short ConfigManager::getMinChannels() {return minChannels;}
unsigned short ConfigManager::getMaxChannels() {return maxChannels;}
void ConfigManager::setVolumeReducedInsteadOfMuting(bool v) {reduceVolumeInsteadOfMuting=v;}
void ConfigManager::setLastPositionPlayed(unsigned int v) {lastPositionPlayed=v;}
void ConfigManager::setVolume(unsigned int v) {volume=v;}
void ConfigManager::setRepeatMode(unsigned int v) {repeatMode=v;}
void ConfigManager::setShuffleMode(unsigned int v) {shuffleMode=v;}
void ConfigManager::setMinTime(unsigned int v) {minTime=v;}
void ConfigManager::setMaxTime(unsigned int v) {maxTime=v;}
void ConfigManager::setMinBitrate(unsigned short v) {minBitrate=v;}
void ConfigManager::setMaxBitrate(unsigned short v) {maxBitrate=v;}
void ConfigManager::setMinChannels(unsigned short v) {minChannels=v;}
void ConfigManager::setMaxChannels(unsigned short v) {maxChannels=v;}
